package org.chmodke.proxy.socks.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 常量
 *
 * @author kehao
 */
public class C {
    public static final String MAIN_LOG = "[SSR]";
    public static final String PROXY_LOG = "[PROXY]";
    public static final String TEST_LOG = "[TEST]";
    private static final Logger logger = LoggerFactory.getLogger(C.class);
    private static final int ACCEPT_CORE_SIZE = 4;
    private static final int ACCEPT_MAX_CORE_SIZE = 50;
    private static final int ACCEPT_QUEUE_SIZE = 50;
    private static final int IDLE_ALIVE = 60;
    /**
     * 请求队列
     */
    private static final BlockingQueue<Runnable> ACCEPT_QUEUE = new LinkedBlockingQueue<>(ACCEPT_QUEUE_SIZE);
    private static final AtomicLong ACCEPT_INDEX = new AtomicLong(1);
    /**
     * 请求处理线程池
     */
    public static final ThreadPoolExecutor ACCEPT = new ThreadPoolExecutor(ACCEPT_CORE_SIZE, ACCEPT_MAX_CORE_SIZE,
            IDLE_ALIVE, TimeUnit.SECONDS, ACCEPT_QUEUE, new NamedThreadFactory("ACCEPT", ACCEPT_INDEX),
            new LogRejectedExecutionHandler());

    private static final int PROXY_CORE_SIZE = 4;
    private static final int PROXY_MAX_CORE_SIZE = 100;
    /**
     * 转发队列
     */
    private static final BlockingQueue<Runnable> PROXY_QUEUE = new SynchronousQueue<>();
    private static final AtomicLong PROXY_INDEX = new AtomicLong(1);
    /**
     * 数据转发线程池
     */
    public static final ThreadPoolExecutor PROXY = new ThreadPoolExecutor(PROXY_CORE_SIZE, PROXY_MAX_CORE_SIZE,
            IDLE_ALIVE, TimeUnit.SECONDS, PROXY_QUEUE, new NamedThreadFactory("PROXY", PROXY_INDEX),
            new LogRejectedExecutionHandler());

    /**
     * 线程池状态
     */
    public static void statistic() {
        logger.info("accept thread pool statistic: active({}), queue({}), poolsize({}).",
                ACCEPT.getActiveCount(), ACCEPT_QUEUE.size(), ACCEPT.getPoolSize());
        logger.info("proxy thread pool statistic: active({}), queue({}), poolsize({}).",
                PROXY.getActiveCount(), PROXY_QUEUE.size(), PROXY.getPoolSize());
    }

    private static class NamedThreadFactory implements ThreadFactory {
        private final String prefix;
        private final AtomicLong threadIndex;

        public NamedThreadFactory(String prefix, AtomicLong threadIndex) {
            this.prefix = prefix;
            this.threadIndex = threadIndex;
        }

        @Override
        public Thread newThread(Runnable r) {
            if (threadIndex.get() < 0) {
                threadIndex.set(1);
            }
            return new Thread(r, prefix + "_" + threadIndex.getAndIncrement());
        }
    }

    private static class LogRejectedExecutionHandler implements RejectedExecutionHandler {
        private static final Logger logger = LoggerFactory.getLogger(LogRejectedExecutionHandler.class);

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            logger.warn("{} The system is busy, please wait.", PROXY_LOG);
        }
    }
}
